#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from django.shortcuts import render
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q  #可完成并集
from django.views.generic.base import View
from django.contrib.auth.hashers import make_password
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse

from .models import UserProfile, EmailVerifyRecord,Banner
from .forms import LoginForm, ForgetrForm, ModifyPwdForm, RegisterForm, UploadImageForm, UserInfoForm
from utils.email_send import send_register_email
from utils.mixin_utils import LoginRequiredMixin
from operation.models import UserCourse, UserFavorite, UserMessage

from organization.models import CourseOrg, Teacher
from courses.models import Course
import datetime


from pure_pagination import Paginator, EmptyPage, PageNotAnInteger      # 分页功能
# UserCourse用于存放用户和课程之间的表
# UserFavorite 用于保存用户收藏的表
# Create your views here.


class CustomBackend(ModelBackend):
    # 邮箱 用户名均可登录 # 相当于调用了自定义authenticate的方法
    def authenticate(self, username=None, password=None, **kwargs):
        try:
            # Q 进行并集或交集的随意排版
            user = UserProfile.objects.get(Q(username=username)|Q(email=username))
            # 密码是以密文形式存储 无法拿明文去匹配
            if user.check_password(password):  # 加密对比
                return user
        except Exception as e:
            return None


# 2018/4/12配置
class LogoutView(View):
    '''
    用户退出
    '''
    def get(self, request):
        logout(request)   # 登出
        # 登出之后 重定向到 首页
        # 使用重定向View 进行重定向
        # reverse将URL名称进行反解得到地址 供HttpRespnseRedirect调用
        return HttpResponseRedirect(reverse("index"))



# 基于类的方法
class LoginView(View):
    # 无需进行 get post 方法判断 由类进行自动判断
    def get(self,request):
        return render(request, 'login.html', {})
    def post(self,request):
        # 进行验证 【调用系统form】
        login_form = LoginForm(request.POST)  # 会自动对应到 Form中 前提是 html页面中的username 必须与【LoginView】form验证中的username保持一致
        if login_form.is_valid():
            # 是否有错 是否为空。。。
            user_name = request.POST.get("username", "")
            pass_word = request.POST.get("password", "")
            # 拿到用户名和密码 前去登录验证 是否合法
            user = authenticate(username=user_name, password=pass_word)
            if user is not None:
                if user.is_active:
                    login(request, user) # 使用Django自带函数 实际是对request进行操作 写入了一些信息
                    # render时 就会回到浏览器信息
                    # return render(request, "index.html")   # 会导致 重新登录时拿不到当前用户数据
                    return HttpResponseRedirect(reverse("index"))
                else:
                    return render(request, "login.html", {"msg":"用户名未激活！"})
            else:
                return render(request, "login.html", {"msg":"用户名或密码错误！"})
        else:
            # 验证失败
            # print 'test---->',login_form.errors
            return render(request, "login.html", {"login_form":login_form})  # request 注册到 index.html

# 此为基于函数的方法进行登录验证 现已更改为类操作 LoginView 进行继承现有集成操作进行登录 无需编写过多验证
# def user_login(request):
#     '''
#     处理用户登录 判断其登录方法
#     :param request:
#     :return:
#     '''
#     if request.method == 'POST':
#         user_name = request.POST.get("username", "")
#         pass_word = request.POST.get("password", "")
#         # 拿到用户名和密码 前去登录验证 是否合法
#         user = authenticate(username=user_name, password=pass_word)
#         if user is not None:
#             login(request, user) # 使用Django自带函数 实际是对request进行操作 写入了一些信息
#             # render时 就会回到浏览器信息
#             return render(request, "index.html")
#         else:
#             return render(request, "login.html", {"msg":"用户名或密码错误！"})  # request 注册到 index.html
#     elif request.method == 'GET':
#         return render(request, 'login.html', {})

# 激活处理
class ActiveUserView(View):
    def get(self, request, active_code):
        # 取 url参数
        all_record = EmailVerifyRecord.objects.filter(code=active_code)
        if all_record:
            # 取到验证数据
            for record in all_record:
                email = record.email
                user = UserProfile.objects.get(email=email)
                user.is_active = True
                user.save()
                # 可进行验证
                # 添加欢迎信息
                current_user = UserMessage()
                current_user.id = user.id
                current_user.message = u"欢迎加入微慕课在线学习网"
                current_user.has_read = False
                current_user.add_time = datetime.datetime.now()
                current_user.save()
        else:
            # 如果用户不存在 链接有误
            return render(request, "active_error.html")
        return render(request, "login.html")


# 处理前端请求的类
class RegisterView(View):
    # 注册新用户
    def get(self,request):
        # 实例化
        register_form = RegisterForm()
        return render(request,"register.html",{'register_form':register_form})
    def post(self,request):
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            # 取出用户和密码
            user_name = request.POST.get("email", "")  # 取email参数内容
            # 判断用户是否已经存在
            if UserProfile.objects.filter(email=user_name):
                return render(request, "register.html", {"register_form":register_form, "msg":"用户已经存在"})
                # 滞后要回填用户信息 要处理表单数据（form）--"register_form":register_form
            pass_word = request.POST.get("password", "")
            # 写入userprofile的后台逻辑
            user_profile = UserProfile()
            user_profile.username = user_name
            user_profile.email = user_name
            # 用户初始注册 处于未激活状态
            user_profile.is_active = False
            # 对密码加密保存
            user_profile.password = make_password(pass_word)
            # userprofile完成
            user_profile.save()  # 存到数据库
            send_register_email(user_name, "register") # 邮箱 注册类型
            # 返回页面 否则报错如下
            # Exception Type:	ValueError
            # Exception Value:
            # The view users.views.RegisterView didn't return an HttpResponse object. It returned None instead.
            # 后添加 欢迎信息

            return render(request, "login.html")
        else:
            return render(request, "register.html", {"register_form":register_form})



class ForgetPwdView(View):
    '''
    处理用户忘记密码
    '''
    def get(self, request):
        forget_form = ForgetrForm()
        return render(request, "forgetpwd.html", {"forget_form":forget_form})  # forget_form 将表单内容传递到 模板中

    def post(self, request):
        # post 后台逻辑
        forget_form = ForgetrForm(request.POST)  # 此处一定要传递dict类型 只传递request是有问题的
        if forget_form.is_valid():
            email = request.POST.get("email", "")
            # 生成随机字符串  此处用于找回密码
            send_register_email(email, "forget")
            return render(request, "send_success.html")  # forget_form 将表单内容传递到 模板中
        else:
            # 发送失败 继续返回
            return render(request, "forgetpwd.html", {"forget_form":forget_form})

# 重设密码类
class ResetView(View):
    def get(self, request, active_code):
        # 取 url参数
        all_record = EmailVerifyRecord.objects.filter(code=active_code)
        if all_record:
            # 取到验证数据
            for record in all_record:
                # 如果查找到 就返回到重置密码页面 需要传值 告诉是哪个用户在重置密码
                email = record.email
                return render(request, 'password_reset.html', {"email":email})
        else:
            # 如果用户不存在 链接有误
            return render(request, "active_error.html")
        return render(request, "login.html")


class ModifyPwdView(View):
    '''
    修改用户密码
    '''
    def post(self, request):
        modify_form = ModifyPwdForm(request.POST)
        if modify_form.is_valid():
            pwd1 = request.POST.get("password1", "")  # 取表单提交数据
            pwd2 = request.POST.get("password2", "")  # 取表单提交数据
            # 取出email 用以知道修改的是安格用户【email】
            email = request.POST.get("email", "")
            if pwd1 != pwd2:
                return render(request, 'password_reset.html', {"email":email, "msg":"密码不一致！"})
            # 否则密码一致 进行修改
            user = UserProfile.objects.get(email=email)
            user.password = make_password(pwd2)  # 加密保存
            user.save()
            # 返回登录页面
            return render(request, 'login.html')
        # 若失败的话
        else:
            email = request.POST.get("email", "")
            return render(request, 'password_reset.html', {"email":email, "modify_form":modify_form})


# 处理用户个人信息
class UserinfoView(LoginRequiredMixin, View):
    '''
    用户个人信息  登录之后才能操作
    进行修改 个人信息表单
    '''
    def get(self, request):
        current_page = "self_info"
        return render(request, 'usercenter-info.html', {
            "current_page":current_page,
        })

    def post(self, request):
        # 此处不是新增 是修改 则需要指明实例 是哪个实例 即对哪个进行修改  若无instance 会在save时新增加一个用户的
        user_info_form = UserInfoForm(request.POST, instance=request.user)  # 调用 UserInfoForm表单
        if user_info_form.is_valid():
            # 验证 is_valid()要返回错误信息
            # print 'user_info_form', user_info_form
            # print type(user_info_form)
            user_info_form.save()
            return HttpResponse('{"status":"success"}', content_type='application/json')  # 返回json字符串
            # 若不返回json 就会报错
        else:
            return HttpResponse(json.dumps(user_info_form.errors), content_type='application/json')  # 返回json字符串



class UploadImageView(LoginRequiredMixin, View):
    '''
    用户修改头像 post处理上传头像 专门顶一个form 用来处理文件的上传
    '''
    def post(self, request):
        '''
        好处 image会把用户上传的文件保存到form 可以像以前一样直接使用form
        :param request:
        :return:
        '''
        image_form = UploadImageForm(request.POST, request.FILES, instance=request.user)   # 需要传递第二个参数 而且与之前不一样
        if image_form.is_valid():
            image = image_form.cleaned_data['image']
            image_form.save()
            # 需要返回json 不然会出错 不影响运行 因为 修改是异步的
            return HttpResponse('{"status":"success"}', content_type='application/json')  # 返回json字符串
        else:
            return HttpResponse('{"status":"fail"}', content_type='application/json')  # 返回json字符串




class UpdatePwdView(View):
    '''
    在个人中心修改用户密码 ajax请求 只能返回json
    '''
    def post(self, request):
        modify_form = ModifyPwdForm(request.POST)
        if modify_form.is_valid():
            pwd1 = request.POST.get("password1", "")  # 取表单提交数据
            pwd2 = request.POST.get("password2", "")  # 取表单提交数据

            if pwd1 != pwd2:
                return HttpResponse('{"status":"fail", "msg":"密码不一致"}', content_type='application/json')  # 返回json字符串
            # 否则密码一致 进行修改
            user = request.user
            user.password = make_password(pwd2)  # 加密保存
            user.save()

            return HttpResponse('{"status":"success"}', content_type='application/json')  # 返回json字符串
        # 若失败的话
        else:
            # 利用python提供的json工具 直接将form中的错误变成字符串
            return HttpResponse(json.dumps(modify_form.errors), content_type='application/json')  # 返回json字符串



# 更换邮箱
class SendEmailCodeView(LoginRequiredMixin, View):
    '''
    前置条件 ： 用户必须已登录[LoginRequiredMixin负责校验]
    发送邮箱验证码
    '''
    def get(self, request):
        # 拿到当前邮箱  另外 更换的邮箱必须是未注册过的
        email = request.GET.get('email', '')

        if UserProfile.objects.filter(email=email):
            return HttpResponse('{"email":"邮箱已经存在！"}', content_type='application/json')  # 返回json字符串
        # 调用 utils工具包中的邮箱处理
        send_register_email(email, "update_email")
        return HttpResponse('{"status":"success"}', content_type='application/json')  # 返回json字符串


class UpdateEmailView(LoginRequiredMixin, View):
    '''
    验证邮箱之后 修改 邮箱
    '''
    def post(self, request):
        email = request.POST.get('email', '')
        code = request.POST.get('code', '')  # 邮箱验证码此时的code为4位


        # 先定义一个变量
        existed_records = EmailVerifyRecord.objects.filter(email=email, code=code, send_type='update_email')
        if existed_records:
            # 已存在该邮箱 即验证邮箱列表存在该记录 邮箱 验证码匹配成功
            user = request.user
            user.email = email
            user.save()
            return HttpResponse('{"status":"success"}', content_type='application/json')  # 返回json字符串
        else:
            return HttpResponse('{"email":"验证码出错！"}', content_type='application/json')  # 返回json字符串



class MyCourseView(LoginRequiredMixin, View):
    '''
    个人中心 我的课程
    '''
    def get(self, request):
        # request.user 表示当前用户
        current_page = "my_course"
        user_courses = UserCourse.objects.filter(user=request.user,)
        return render(request, 'usercenter-mycourse.html', {
            "user_courses":user_courses,
            "current_page":current_page,
        })


class MyFavOrgView(LoginRequiredMixin, View):
    '''
    个人中心 我的收藏课程机构  UserFavorite
    '''
    def get(self, request):
        # request.user 表示当前用户
        org_list = []
        fav_orgs = UserFavorite.objects.filter(user=request.user, fav_type=2)

        # 标签 活动
        current_page = "my_fav_collection"

        for fav_org in fav_orgs:
            org_id = fav_org.fav_id    # u收藏id
            org = CourseOrg.objects.get(id=org_id)  # 取出课程机构
            org_list.append(org)
        return render(request, 'usercenter-fav-org.html', {
            "org_list":org_list,
            "current_page":current_page,
        })




class MyFavTeacherView(LoginRequiredMixin, View):
    '''
    个人中心 我的收藏授课讲师  UserFavorite
    '''
    def get(self, request):
        # request.user 表示当前用户
        # 标签 活动
        current_page = "my_fav_collection"

        teacher_list = []
        fav_teachers = UserFavorite.objects.filter(user=request.user, fav_type=3)  # 表示收藏讲师
        for fav_teacher in fav_teachers:
            teacher_id = fav_teacher.fav_id    # u收藏id
            teacher = Teacher.objects.get(id=teacher_id)  # 取出课程机构
            teacher_list.append(teacher)
        return render(request, 'usercenter-fav-teacher.html', {
            "teacher_list":teacher_list,
            "current_page":current_page,
        })



class MyFavCourseView(LoginRequiredMixin, View):
    '''
    个人中心 我的收藏授课讲师  UserFavorite
    '''
    def get(self, request):
        # request.user 表示当前用户
        # 标签 活动
        current_page = "my_fav_collection"

        course_list = []
        fav_courses = UserFavorite.objects.filter(user=request.user, fav_type=1)  # 1表示收藏课程
        for fav_course in fav_courses:
            course_id = fav_course.fav_id    # u收藏id
            course = Course.objects.get(id=course_id)  # 取出课程机构
            course_list.append(course)
        return render(request, 'usercenter-fav-course.html', {
            "course_list":course_list,
            "current_page":current_page,
        })



class MyMessageView(View):
    """
    用户个人中心页 我的消息
    """
    def get(self, request):
        # 标签 活动
        current_page = "my_message"

        # userMessage_list = [0]
        # userMessage_list.append(request.user.id)
        all_messages = UserMessage.objects.filter(user=request.user.id)  #user__in=userMessage_list)

        # 用户进入个人信息页后 清空未读消息的记录  添加user 只能清空自己的消息

        all_unread_message = UserMessage.objects.filter(user=request.user.id, has_read=False)

        for unread_message in all_unread_message:
            unread_message.has_read = True
            # unread_message.message
            unread_message.save()

        # 对个人消息进行分页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1

        p = Paginator(all_messages, 2, request=request)

        messages = p.page(page)

        return render(request, 'usercenter-message.html', {
            "messages": messages,
            "current_page":current_page,
        })


class IndexView(View):
    """
    微慕课在线网 处理首页
    """
    def get(self, request):
        # 取出轮播图
        # print 1/0  调出 500页面
        all_banner = Banner.objects.all().order_by('index')
        # 广告位 需要设置标志
        courses = Course.objects.filter(is_banner=False)[:6]
        banner_courses = Course.objects.filter(is_banner=True)[:3]
        courses_orgs = CourseOrg.objects.all()[:15]
        return render(request, 'index.html', {
            'all_banner': all_banner,
            'courses': courses,
            'banner_courses': banner_courses,
            'courses_orgs': courses_orgs,
        })


def page_not_found(request):
    # 全局404处理函数
    from django.shortcuts import render_to_response
    response = render_to_response('404.html', {})
    response.status_code = 404
    return response


def page_error(request):
    # 全局500处理函数
    from django.shortcuts import render_to_response
    response = render_to_response('500.html', {})
    response.status_code = 500
    return response
